/**
 * instanceof是判断构造函数的原型在不在实例对象的原型连上
 * obj 实例对象 实例对象有__proto__属性指向生成该实例对象的原型，也就是prototype
 * constructor 构造函数
 */

const instanceOf = (obj, constructor) => {
    // 判断传入的实例对象是否是普通对象或者函数
    // 函数也是对象，它也有__proto__属性，函数都是有Function构造函数生成的
    if (typeof obj !== 'object' && typeof obj !== 'function') return false
    // 判断传入的构造函数是否是函数，不是的话直接返回false
    if (typeof constructor !== 'function') return false
    let objProto = obj.__proto__
    const constructorProto = constructor.prototype
    // 递归查找实例对象的__proto__属性，也就是顺着原型链查找，看构造函数的原型是否在原型链上
    while(true) {
        // 原型链的尽头是null，如果一直没有找到，则返回false
        if (objProto === null) return false
        // 构造函数的原型在实例对象的原型链上，返回true
        if (objProto === constructorProto) return true
        // 即不是null，也没有找到，则顺着原型链上继续查找
        objProto = objProto.__proto__
    }
}



/**
 * new 操作符是从一个构造函数中创建一个实例
 * 这个实例的__proto__指向构造函数的prototype
 * 这个对象的属性继承构造函数的属性
 * 如果这个函数有返回值，则是返回这个函数的运行结果
 */

const myNew = (fn, ...rest) => {
    if (!fn || typeof fn !== 'function') {
        throw 'Parameter is not a number!';
    }
    // 创建一个空对象，将fn的原型指向obj的__proto__上
    const obj = Object.create(fn.prototype)
    // 调用fn构造函数，将属性都加入到obj上，并且返回构造函数的运行结果
    const res = fn.apply(obj, rest)
    // 如果构造函数运行后返回了一个引用类型的数据，则直接返回运行结果
    if (res && (typeof res === 'object' || typeof res === 'function')) return res
    // 如果返回的是普通值，或者没有返回值，则返回新创建的对象
    return obj
}